<template>
  <div class="container">
    <a-upload
      ref="uploadRef"
      :action="action"
      :headers="headers"
      :show-file-list="true"
      :limit="limit"
      :file-list="fileList"
      image-preview
      :on-before-upload="beforeUpload"
      :on-before-remove="beforeRemove"
      @change="onChange"
      @success="uploadSuccess"
    />
  </div>
</template>
  <script setup lang="ts">
import { ref, watch, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { FileItem, Message } from '@arco-design/web-vue';
import { getToken } from '@/utils/auth';
import { FileInfo } from '@/api/common';

const { t } = useI18n();

const loading = ref(false);

// 触发父组件事件 刷新用户列表
const props = withDefaults(
  defineProps<{
    url?: string;
    modelValue?: string | Array<string> | any;
    limit?: number; // 图片数量限制
    fileType?: Array<string>; // 大小限制(MB)
    fileSize?: number; // 文件类型, 例如['png', 'jpg', 'jpeg']
    isShowTip?: boolean; // 是否显示提示
  }>(),
  {
    url: '/common/file/upload', // 默认值
    limit: 5,
    fileType: () => ['png', 'jpg', 'jpeg'],
    fileSize: 10,
    isShowTip: true,
  }
);

interface EmitEvent {
  (e: 'update:modelValue', params: string): void;
}

const emit = defineEmits<EmitEvent>();
const modelValue = computed({
  get() {
    return props.modelValue;
  },
  set(value: string) {
    emit('update:modelValue', value);
  },
});

// 上传地址
const BASE_URL = ref(import.meta.env.VITE_API_BASE_URL);
const action = ref(BASE_URL.value + props.url);
const headers = ref({ Authorization: 'Bearer ' + getToken() });
const uploadRef = ref();
const fileList = ref();

// 上传前校验
const beforeUpload = (file: File) => {
  let isImg = false;
  if (props.fileType.length) {
    let fileExtension = '';
    if (file.name.lastIndexOf('.') > -1) {
      fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1);
    }
    isImg = props.fileType.some((type) => {
      if (file.type.indexOf(type) > -1) return true;
      if (fileExtension && fileExtension.indexOf(type) > -1) return true;
      return Promise.resolve(false);
    });
  } else {
    isImg = file.type.indexOf('image') > -1;
  }
  if (!isImg) {
    Message.error(
      `文件格式不正确，请上传${props.fileType.join('/')}图片格式文件!`
    );
    return Promise.resolve(false);
  }
  if (file.name.includes(',')) {
    Message.error('文件名不正确，不能包含英文逗号!');
    return Promise.resolve(false);
  }
  if (props.fileSize) {
    const isLt = file.size / 1024 / 1024 < props.fileSize;
    if (!isLt) {
      Message.error(`上传头像图片大小不能超过 ${props.fileSize} MB!`);
      return Promise.resolve(false);
    }
  }
  return Promise.resolve(true);
};

// 删除图片
const beforeRemove = (file: FileItem) => {
  const findex = fileList.value.map((f) => f.name).indexOf(file.name);
  if (findex > -1) {
    fileList.value.splice(findex, 1);
  }
  modelValue.value = listToString(fileList.value);
  return Promise.resolve(true);
};

// 上传文件成功
const uploadSuccess = (resp: any) => {
  const res = resp.response;
  if (res.code != 200) {
    Message.error(res.msg);
    loading.value = false;
    return;
  }
  const data: FileInfo = res.data;
  loading.value = false;
  onOk(data);
};

// 上传文件改变
const onChange = (files: FileItem[]) => {};

// 确认
const onOk = (data: FileInfo) => {
  fileList.value.push({
    uid: data.fileName,
    name: data.fileName,
    url: data.fileUrl,
  });
  modelValue.value = listToString(fileList.value, ',');
  Message.success(t('operations.upload.success'));
};

// 文件对象转成指定字符串分隔
const listToString = (flist: FileItem, separator: string | undefined | any) => {
  let strs = '';
  separator = separator || ',';
  for (let i in flist) {
    if (flist[i].url && flist[i].url.indexOf('blob:') !== 0) {
      strs += flist[i].url + separator;
    }
  }
  return strs != '' ? strs.substr(0, strs.length - 1) : '';
};

// 判断是否为json字符串
const isJson = (str: any) => {
  try {
    JSON.parse(str);
    return true;
  } catch (e) {
    return false;
  }
};

// 监听数据
watch(
  modelValue,
  (newValue: any, oldValue) => {
    if (!newValue) {
      return;
    }
    if (isJson(newValue)) {
      let list: FileInfo[] = JSON.parse(newValue);
      fileList.value = list.map((item) => {
        return {
          uid: item.fileName,
          name: item.fileName,
          url: item.fileUrl,
        };
      });
      return;
    }
    let list: string[] = newValue.split(',');
    fileList.value = list.map((item) => {
      return {
        uid: item.split('/').pop(),
        name: item.split('/').pop(),
        url: item,
      };
    });
  },
  { deep: true }
);
</script>
    <style scoped lang="less">
:deep(.arco-upload-progress) {
  display: none;
}
</style>